﻿using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
namespace System.Web.Mvc
{
    public static class HtmlHelperExtensions
    {
        public static MvcHtmlString BsTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string placeholder, string @class, string type = "text")
        {
            TagBuilder tagBuilder = new TagBuilder("input");
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
            string name = ExpressionHelper.GetExpressionText(expression);
            tagBuilder.GenerateId(name);
            tagBuilder.MergeAttribute("name", name, true);
            tagBuilder.MergeAttribute("type", type);
            tagBuilder.MergeAttribute("placeholder", placeholder);
            tagBuilder.MergeAttributes<string, object>(htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata));
            tagBuilder.AddCssClass(@class);
            return new MvcHtmlString(tagBuilder.ToString());
        }

        public static MvcHtmlString CheckBoxList(this HtmlHelper helper, string name, bool isHorizon = true)
        {
            return CheckBoxList(helper, name, helper.ViewData[name] as IEnumerable<SelectListItem>, new { }, isHorizon);
        }

        public static MvcHtmlString CheckBoxList(this HtmlHelper helper, string name, IEnumerable<SelectListItem> selectList, bool isHorizon = true)
        {
            return CheckBoxList(helper, name, selectList, new { }, isHorizon);
        }

        public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, bool isHorizon = true)
        {
            string[] propertys = expression.ToString().Split(".".ToCharArray());
            string id = string.Join("_", propertys, 1, propertys.Length - 1);
            string name = string.Join(".", propertys, 1, propertys.Length - 1);

            return CheckBoxList(helper, id, name, selectList, new { }, isHorizon);
        }

        public static MvcHtmlString CheckBoxList(this HtmlHelper helper, string name, IEnumerable<SelectListItem> selectList, object htmlAttributes, bool isHorizon = true)
        {
            return CheckBoxList(helper, name, name, selectList, htmlAttributes, isHorizon);
        }

        public static MvcHtmlString CheckBoxList(this HtmlHelper helper, string id, string name, IEnumerable<SelectListItem> selectList, object htmlAttributes, bool isHorizon = true)
        {
            IDictionary<string, object> HtmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

            HashSet<string> set = new HashSet<string>();
            List<SelectListItem> list = new List<SelectListItem>();
            if ((selectList as SelectList) != null)
            {
                string selectedValues = (selectList as SelectList).SelectedValue == null ? string.Empty : Convert.ToString((selectList as SelectList).SelectedValue);
                if (!string.IsNullOrEmpty(selectedValues))
                {
                    if (selectedValues.Contains(","))
                    {
                        string[] tempStr = selectedValues.Split(',');
                        for (int i = 0; i < tempStr.Length; i++)
                        {
                            set.Add(tempStr[i].Trim());
                        }

                    }
                    else
                    {
                        set.Add(selectedValues);
                    }
                }
            }
            foreach (SelectListItem item in selectList)
            {
                item.Selected = (item.Value != null) ? set.Contains(item.Value) : set.Contains(item.Text);
                list.Add(item);
            }
            selectList = list;

            HtmlAttributes.Add("type", "checkbox");
            HtmlAttributes.Add("id", id);
            HtmlAttributes.Add("name", name);
            HtmlAttributes.Add("style", "border:none;");

            StringBuilder stringBuilder = new StringBuilder();

            foreach (SelectListItem selectItem in selectList)
            {
                IDictionary<string, object> newHtmlAttributes = HtmlAttributes.DeepCopy();
                newHtmlAttributes.Add("value", selectItem.Value);
                if (selectItem.Selected)
                {
                    newHtmlAttributes.Add("checked", "checked");
                }

                TagBuilder tagBuilder = new TagBuilder("input");
                tagBuilder.MergeAttributes<string, object>(newHtmlAttributes);
                string inputAllHtml = tagBuilder.ToString(TagRenderMode.SelfClosing);
                string containerFormat = isHorizon ? @"<label class='checkbox'> {0}  {1}</label>" : @"<label class='checkbox line'> {0}  {1}</label>";
                stringBuilder.AppendFormat(containerFormat,inputAllHtml, selectItem.Text); 
            }
            return MvcHtmlString.Create(stringBuilder.ToString());

        }
        
        private static IDictionary<string, object> DeepCopy(this IDictionary<string, object> ht)
        {
            Dictionary<string, object> _ht = new Dictionary<string, object>();

            foreach (var p in ht)
            {
                _ht.Add(p.Key, p.Value);
            }
            return _ht;
        }

        public static MvcHtmlString RadioBoxList(this HtmlHelper helper, string name)
        {
            return RadioBoxList(helper, name, helper.ViewData[name] as IEnumerable<SelectListItem>, new { });
        }

        public static MvcHtmlString RadioBoxList(this HtmlHelper helper, string name, IEnumerable<SelectListItem> selectList)
        {
            return RadioBoxList(helper, name, selectList, new { });
        }

        public static MvcHtmlString RadioBoxList(this HtmlHelper helper, string name, IEnumerable<SelectListItem> selectList, object htmlAttributes, bool isHorizon = true)
        {
            IDictionary<string, object> HtmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

            HtmlAttributes.Add("type", "radio");
            HtmlAttributes.Add("name", name);

            StringBuilder stringBuilder = new StringBuilder();
            int i = 0;
            int j = 0;
            foreach (SelectListItem selectItem in selectList)
            {
                string id = string.Format("{0}{1}", name, j++);

                IDictionary<string, object> newHtmlAttributes = HtmlAttributes.DeepCopy();
                newHtmlAttributes.Add("value", selectItem.Value);
                newHtmlAttributes.Add("id", id);
                if ((selectList as SelectList) != null)
                {
                    var selectedValue = (selectList as SelectList).SelectedValue;
                    if (selectedValue == null)
                    {
                        if (i++ == 0)
                            newHtmlAttributes.Add("checked", null);
                    }
                    else if (selectItem.Value == selectedValue.ToString())
                    {
                        newHtmlAttributes.Add("checked", null);
                    }
                }
                TagBuilder tagBuilder = new TagBuilder("input");
                tagBuilder.MergeAttributes<string, object>(newHtmlAttributes);
                string inputAllHtml = tagBuilder.ToString(TagRenderMode.SelfClosing); 
                string containerFormat = isHorizon ? @" {0}  <label class='radio' for='{2}'>{1}</label>" : @" {0}  <label class='radio line' for='{2}'>{1}</label>"; 
                stringBuilder.AppendFormat(containerFormat, inputAllHtml, selectItem.Text, id);
                 
            }
            return MvcHtmlString.Create(stringBuilder.ToString());

        }

        public static MvcHtmlString RadioBoxList<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, object htmlAttributes, bool isHorizon = true)
        {
            string[] propertys = expression.ToString().Split(".".ToCharArray());
            
            string name = string.Join(".", propertys, 1, propertys.Length - 1);
            return RadioBoxList(helper, name, selectList, htmlAttributes, isHorizon); 
        }  
    }
}
   